/*
 * @Author: fanjs
 * @Date: 2024-03-21 16:02:00
 * @Description: 操作记录模型
 */
import { Table, Column, DataType, ForeignKey, BelongsTo } from 'sequelize-typescript'
import { BaseModel } from '@core/db'
import BillModel, { RateType } from './bill'
import { Pagination, PaginationParams, PaginationResult, DateUtil } from '@core/util'

// 账单类型
export type BillType = 'save' | 'borrow'
export type MoneyType = 'principal' | 'interest'


/**
 * 根据账单类型变化 hasMoneyType 可变 
 * save   = false追加存款 true取款
 * borrow = false追加借款 true还款
 */
export interface RecordAttributes {
  id?: number
  billId: number
  billType?: BillType
  otherType?: string
  needMoneyType?: boolean
  moneyType?: MoneyType
  amount: number
  beforePrincipal: number
  afterPrincipal: number
  beforeInterest: number
  afterInterest: number
  operator: string
  operatorName: string
  remark?: string
}

@Table({ tableName: 'record' })
class RecordModel extends BaseModel<RecordModel, RecordAttributes> {
  @Column({
    type: DataType.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  })
  declare id: number

  @ForeignKey(() => BillModel)
  @Column
  declare billId: number

  @BelongsTo(() => BillModel)
  bill!: BillModel

  @Column({
    type: DataType.ENUM('save', 'borrow'),
    comment: '账单类型',
  })
  declare billType: BillType

  @Column({
    type: DataType.STRING,
    allowNull: true,
    comment: '其他操作类型',
  })
  declare otherType: string

  @Column({
    type: DataType.BOOLEAN,
    comment: '是否有金额类型',
  })
  declare needMoneyType: boolean

  @Column({
    type: DataType.ENUM('principal', 'interest'),
    comment: '金额类型：本金、利息',
  })
  declare moneyType: MoneyType

  @Column({
    type: DataType.DECIMAL(10, 2),
    comment: '操作金额',
  })
  declare amount: number

  @Column({
    type: DataType.DECIMAL(10, 2),
    comment: '操作前本金',
  })
  declare beforePrincipal: number

  @Column({
    type: DataType.DECIMAL(10, 2),
    comment: '操作后本金',
  })
  declare afterPrincipal: number

  @Column({
    type: DataType.DECIMAL(10, 2),
    comment: '操作前利息',
  })
  declare beforeInterest: number

  @Column({
    type: DataType.DECIMAL(10, 2),
    comment: '操作后利息',
  })
  declare afterInterest: number

  @Column({
    type: DataType.STRING,
    comment: '操作人ID',
  })
  declare operator: string

  @Column({
    type: DataType.STRING,
    comment: '操作人昵称',
  })
  declare operatorName: string

  @Column({
    type: DataType.STRING,
    comment: '备注',
  })
  declare remark: string

  keys() {
    this.append('created_at')
  }

  /**
   * 获取操作记录列表
   * @param billId 账单ID
   * @param params 查询参数
   * @returns 操作记录列表和总数
   */
  static async getRecordList(billId: number, params: { page: number; pageSize: number } & PaginationParams): Promise<PaginationResult<RecordModel>> {
    const { page, pageSize } = params

    const { count, rows } = await RecordModel.findAndCountAll({
      where: { billId },
      order: [['created_at', 'DESC']],
      offset: (page - 1) * pageSize,
      limit: pageSize
    })

    // 格式化时间字段
    const formattedRows = rows.map(item => {
      const recordData = item.toJSON();
      return {
        ...recordData,
        created_at: DateUtil.formatDateTime(recordData.created_at)
      };
    });

    return Pagination.createResult(count, formattedRows, { page, pageSize });
  }

  /**
   * 创建操作记录
   * @param data 操作记录数据
   * @param options 创建选项
   * @returns 创建的操作记录
   */
  static async createRecord(data: RecordAttributes, options?: any) {
    return await RecordModel.create(data, options)
  }

  /**
   * 计算指定次数的利息
   * @param rate 利率 | 日利率 | 月利率
   * @param principal 本金
   * @param count 计息次数
   * @returns 利息
   */
  static calculateInterest(rate: number, principal: number, count: number) {
    return Number((principal * rate / 100 * count).toFixed(3))
  }

  /**
   * 计算计息次数
   * @param lastInterestDate 上次计息日期
   * @param now 当前日期
   * @param rateType 利率类型
   * @returns 次数
   */
  static calculateCount(lastInterestDate: string | Date, now: string | Date, rateType: RateType) {
    const dateKey = rateType === 'M' ? 'month' : 'day'
    return Math.floor(DateUtil.diffMonthsOrDays(lastInterestDate, now, dateKey))
  }
}

export default RecordModel 